/*=============================================================================
#     FileName: event_handler.cpp
#         Desc: 
#       Author: Ace
#        Email: goace@acm.org
#     HomePage: http://www.goace.co.cc
#      Version: 0.0.1
#   LastChange: 2011-04-12 20:50:58
#      History:
=============================================================================*/

#include  <stdio.h>
#include  <iostream>
#include  <string.h>
#include  <string>
#include  <sys/types.h>
#include  <sys/stat.h>
#include  <fcntl.h>
#include  <errno.h>
#include  <stdlib.h>
#include  "gserver.h"
#include  "event_handler.h"

using std::string;
using std::cout;
using std::endl;

/* ---------------------------------------------------------------*/
/**
 * 函数简介:  data进程中读取用户ID的函数 
 *
 * 参数: ptr 对方用户信息指针
 * 参数: name 用户缓冲区
 *
 * 返回值： -1表示失败 0表示成功
 */
/* ---------------------------------------------------------------*/
int data_read_id(data_sock_info_t *ptr)
{
	int res;
	if( (res=readn(ptr->sock_fd,ptr->usr_name,USR_LEN)) < 0 )  
	{
		if( errno == EAGAIN || errno == EWOULDBLOCK )
		{
			ptr->state = SYNC_WAIT_ID;
			perror("read");
			return -1;
		}
		data_error("read",ptr);
		return -1;
	}

	//ptr->usr_name = "";
	//ptr->usr_name += name;
	//cout << name << endl;
	return 0;
}

/* ---------------------------------------------------------------*/
/**
 * 函数简介: 打开日志文件 
 *
 * 参数: ptr 指针
 *
 * 返回值:   -1失败 0成功
 */
/* ---------------------------------------------------------------*/
int open_log_file(data_sock_info_t *ptr)
{
	char log[USR_LEN];
	snprintf(log,USR_LEN,"%s/%s/.log/%d.log",SRV_ROOT,
			ptr->usr_name,ptr->peer_version);
	
//	snprintf(log,USR_LEN,"%s/%s/.log/%d.log",SRV_ROOT,
//			"87",ptr->peer_version);

	if( (ptr->file_fd = open(log,O_RDONLY)) < 0 )
	{
		data_error("open log file",ptr);
		return -1;
	}

	struct stat buf;

	if( fstat(ptr->file_fd,&buf) < 0 )
	{
		data_error("stat",ptr);
		return -1;
	}

	(ptr->peer_version)++;
	ptr->tsfd = 0;
	ptr->total = buf.st_size;
	
	return 0;
}


/* ---------------------------------------------------------------*/
/**
 * 函数简介:  读取版本号信息
 *
 * 参数: flag 有peer和real两种情况
 * 参数: ptr  指向用户信息的指针
 *
 * 返回值:   -1表示成功 0表示失败
 */
/* ---------------------------------------------------------------*/
int data_read_version(int flag, data_sock_info_t *ptr)
{
	if( flag == SYNC_WAIT_PEER )
	{
		if( readn(ptr->sock_fd,&ptr->peer_version,
					sizeof(ptr->peer_version)) < 0 )
		{
			if( errno == EAGAIN || errno == EWOULDBLOCK )
			{
				ptr->state = SYNC_WAIT_PEER;
				return -1;
			}
			
			data_error("read",ptr);
			return -1;
		}
		
		return 0;
	} 
	else if( flag == SYNC_WAIT_REAL)
	{
		if( readn(ptr->sock_fd,&ptr->real_version,
					sizeof(ptr->real_version)) < 0 )
		{
			if( errno == EAGAIN || errno == EWOULDBLOCK )
			{
				ptr->state = SYNC_WAIT_REAL;
				return -1;
			}
			
			data_error("read",ptr);
			return -1;
		}

		return 0;
	}
}

/* ---------------------------------------------------------------*/
/**
 * 函数简介:  处理data_process中的错误退出
 *
 * 参数: msg  提供给perror的字符串
 * 参数: info 用户信息指针
 */
/* ---------------------------------------------------------------*/
void data_error(const char* msg, data_sock_info_t* info)
{
	perror(msg);
	close(info->sock_fd);

	if( info->transfering )
		close(info->file_fd);

	delete info;
}

/* ---------------------------------------------------------------*/
/**
 * 函数简介:  处理用户退出(包括正常与非正常)
 *
 * 参数: ptr  用户信息
 */
/* ---------------------------------------------------------------*/
void usr_exit(ctl_sock_info_t* info)
{
	if( !info )
		return;
	
	close(info->fd);
	
	if( strlen(info->usr_name) > 0 )
	{
#ifdef DEBUG
		cout << info->usr_name << " exit" << endl;
#endif
		//如果登录期间发生了更新
		//则把更新写入日志
		if( !info->history.empty() )
		{
			info->version++;
			
			char version_file[PATH_LEN];
			snprintf(version_file,PATH_LEN,"%s/%s/.version",
					SRV_ROOT,info->usr_name);

			//打开version file
			int vf_fd = open(version_file,O_WRONLY);
			if( vf_fd < 0 )
			{
				perror("exit:open version file");
				return;
			}

			//写入版本号
			if( write(vf_fd,&(info->version),sizeof(info->version)) < 0 )
			{
				perror("write to version file");
				return;
			}

			close(vf_fd);

			//生成日志
			char log[PATH_LEN];
			snprintf(log,PATH_LEN,"%s/%s/.log/%d.log",SRV_ROOT,
						info->usr_name, info->version);

			int log_fd = open(log, O_WRONLY | O_CREAT, 0766);
			if( log_fd < 0 )
			{
				perror("open log");
				return;
			}

			for( int i = 0; i < info->history.size() ; i++ )
			{
				if( write(log_fd,info->history[i],sizeof(ctl_pkg_t)) < 0 )
				{
					perror("write to log");
					return;
				}
				delete(info->history[i]);
			}

			close(log_fd);
		}
	}
	
	delete(info);
}


